Prototyping a Wireless Controllable Entrance/Exit Gate Controller Using an ESP32 and a Servo Motor
この記事には日本語版があります。
Introduction
There is an Amazon Go like cashless shopping area(we call it a "walk-through") in "Developers.IO CAFE" operated by Classmethod, Inc. We have installed no bars or flappers at the entrance and the exit of the "walk-through" so far. Though it gave good opened impressions to our customers that no existence of bars or flappers, sometimes the customers confused which is the entrance and which is the exit. In this blog post, I will explain how I prototyped an ultra-simple wireless controllable entrance/exit gate controller by a servo motor and an ESP32 for making sure whether it is effective for good customer experiences or not.
Concept
- Attach a bar made of Styrofoam to a servo motor. The servo rotates the bar 90 degrees.
- The horizontal state of the bar indicates the gate is opened, and the vertical state of the bar indicates the gate is closed.
- A microcontroller
- Use an Akizuki's ESP32-DevKitC for BLE GATT Write to control gate open/close
- Use nkolban's ESP32_BLE_Arduino library
- A servo motor
- Use Vstone's "standard servo motor type 2"
- Controlled with ESP32's PWM output
- Fixed to the post of the belt partition installed in the cafe
- A styrofoam bar
- Indicates the gate open/close status
- Use a hard one with a diameter of 30mm and a length of 1000mm(sold in Tokyu Hands) cut in half.
- Do not connect to the cafe's "walkthrough" system
- This time, I want to make a working prototype at the fastest speed, so I don't link it with the cafe's walk-through system.
- Manually open and close via BLE
- This time, I want to make a working prototype at the fastest speed, so I don't link it with the cafe's walk-through system.
Prototyping
Torque calculation
The styrofoam bar used to indicate the open and closed state of the gate weighs about 20g for 500mm. Assuming a load of 20g is applied to the end of a 500mm bar when the bar is horizontal, the required torque is 0.02kgf x 0.5m = 0.01kgfm. According to the specifications of the servo motor, its torque is 4.6 kgfm, which seems to be enough.
Controlling a servo motor by PWM
ESP32 has functions with the prefix ledc~~
for controlling LED by PWM.
Since there is no difference between the LED and the servo motor in terms of PWM control, the functions can be used for controlling the servo motor.
I have confirmed that PWM control of servo motor can be dynamically performed using simple CUI via serial port introduced in Sakaji's blog post.
Working code sample
#include <BLEDevice.h> #include <BLEServer.h> #include <BLEUtils.h> #include <BLE2902.h> #define MIN 1 #define MAX 30 int n; int gate_open; BLEServer* pServer = NULL; BLECharacteristic* pCharacteristic = NULL; bool deviceConnected = false; bool oldDeviceConnected = false; #define SERVICE_UUID "YOUR OWN SERVICE UUID" #define CHARACTERISTIC_UUID "YOUR OWN CHARACTERISTIC UUID" String bleSensorName = "YOUR OWN BLE DEVICE NAME"; class MyCallbacks: public BLECharacteristicCallbacks { void onWrite(BLECharacteristic *pCharacteristic) { Serial.println("onWrite"); std::string value = pCharacteristic->getValue(); if (value.length() > 0) { Serial.println("*********"); Serial.print("New value: "); for (int i = 0; i < value.length(); i++) Serial.print(value[i]); Serial.println(); Serial.println("*********"); } if (gate_open == 0) { n = 15; // 90° gate_open = 1; // GATE CLOSED } else { n = 1; // 0° gate_open = 0; // GATE OPENED } } }; void setup() { Serial.begin(115200); Serial.print("> "); ledcSetup(0, 50, 8); // 0ch 50 Hz 8bit resolution ledcAttachPin(15, 0); // 15pin, 0ch n = MIN; gate_open = 0; BLEDevice::init((char *)bleSensorName.c_str()); pServer = BLEDevice::createServer(); pServer->setCallbacks(new MyServerCallbacks()); BLEService *pService = pServer->createService(SERVICE_UUID); pCharacteristic = pService->createCharacteristic( CHARACTERISTIC_UUID, BLECharacteristic::PROPERTY_WRITE ); pCharacteristic->setCallbacks(new MyCallbacks()); // https://www.bluetooth.com/specifications/gatt/viewer?attributeXmlFile=org.bluetooth.descriptor.gatt.client_characteristic_configuration.xml pCharacteristic->addDescriptor(new BLE2902()); pService->start(); pServer->getAdvertising()->start(); // start advertising Serial.println("Setup completed. starting advertising..."); } void loop() { if (Serial.available() > 0) { String s; s = Serial.readStringUntil('\n'); Serial.println(s); int new_n = menu(s); if (new_n != -1) n = new_n; } if (n > MAX) n = MAX; if (n < MIN) n = MIN; ledcWrite(0, n); // disconnecting if (!deviceConnected && oldDeviceConnected) { delay(500); // give the bluetooth stack the chance to get things ready pServer->startAdvertising(); // restart advertising Serial.println("start advertising"); oldDeviceConnected = deviceConnected; } // connecting if (deviceConnected && !oldDeviceConnected) { oldDeviceConnected = deviceConnected; } } int menu(String s) { if (s.equals("?")) { Serial.println("entrance-exit-gate-controller"); Serial.print("> "); return -1; } else if (s.equals("ver")) { Serial.println("0.0.1"); Serial.print("> "); return -1; } else { Serial.println(s); Serial.print("> "); return s.toInt(); } }
Hardware assemble
In this prototype, it is OK if the minimum operation is confirmed, so I assembled it extremely roughly as follows. The servo motor's power(5V) was supplied from the ESP32-DevKitC 5V output pin.
Function check
The following is a video at the time of the function check. Since it is not linked with the walkthrough system, opening and closing the gate is performed by writing the GATT characteristic of the ESP32 via a BLE client application at hand.
Conclusion
In this blog post, I have shown how I prototyped the ultra simple entrance/exit gate which is controlled wirelessly. I would like to complete the following tasks and would like to observe whether it is effective for good customer experiences or not.
- Link to the walk-through system
- Fix the servo motor and the post of the belt partition more firmly
- Make the gate open/close bar look cooler